﻿using System;
using System.IO;
using System.Reflection;
using System.Runtime.Remoting;

namespace CILADA.TestAssemblyFour
{
    class CreatingObjectsWithActivatorFromConstants
    {
        const string ASSEMBLY = "CILADA.TestAssembly.dll";
        const string TYPE = "CILADA.TestAssembly.Giraffe";
        static string ASSEMBLY2 = "CILADA.TestAssembly.dll";
        static string TYPE2 = "CILADA.TestAssembly.Giraffe";
        static readonly string ASSEMBLY3 = "CILADA.TestAssembly.dll";
        static readonly string TYPE3 = "CILADA.TestAssembly.Giraffe";

        public CreatingObjectsWithActivatorFromConstants()
        {
            Console.WriteLine("CreatingLocalObjectsWithActivator:");
            object obj = CreateWithConstants();
            WriteObjectInfo.WriteInfo(obj);
        }

        public object CreateWithConstants()
        {
            object obj = System.Activator.CreateInstance(ASSEMBLY, TYPE);
            obj = ((ObjectHandle)obj).Unwrap();
            return obj;
        }

        public object CreateWithConstants2()
        {
            object obj = System.Activator.CreateInstance(ASSEMBLY2, TYPE2);
            obj = ((ObjectHandle)obj).Unwrap();
            return obj;
        }

        public object CreateWithConstants3()
        {
            object obj = System.Activator.CreateInstance(ASSEMBLY3, TYPE3);
            obj = ((ObjectHandle)obj).Unwrap();
            return obj;
        }
    }

    class CreatingLocalObjectsWithActivator
    {
        public CreatingLocalObjectsWithActivator()
        {
            Console.WriteLine("CreatingLocalObjectsWithActivator:");
            object obj = CreateObject("CILADA.TestAssemblyFour.Hello");
            WriteObjectInfo.WriteInfo(obj);
        }

        public object CreateObject(string typeName)
        {
            Type objToCreate = Type.GetType(typeName);
            object obj = System.Activator.CreateInstance(objToCreate);
            return obj;
        }
    }

    class CreatingForeignObjectsWithActivator
    {
        public CreatingForeignObjectsWithActivator()
        {
            Console.WriteLine("CreatingForeignObjectsWithActivator:");
            object obj = CreateObject("CILADA.TestAssembly.Rock", "CILADA.TestAssembly.dll");
            WriteObjectInfo.WriteInfo(obj);
        }

        public object CreateObject(string typeName, string assemblyName)
        {
            FileInfo fi = new FileInfo(assemblyName);
            object obj = Activator.CreateInstanceFrom(fi.FullName, typeName);
            ObjectHandle handle = (ObjectHandle)obj;
            obj = handle.Unwrap();
            return obj;
        }
    }

    class CreatingObjectsFromAssembly
    {
        public CreatingObjectsFromAssembly()
        {
            Console.WriteLine("CreatingObjectsFromAssembly:");
            object obj = CreateObject("CILADA.TestAssembly.dll", "CILADA.TestAssembly.Rock");
            WriteObjectInfo.WriteInfo(obj);
            Console.WriteLine("CreatingObjectsFromAssembly2:");
            object obj2 = CreateObject2("CILADA.TestAssembly.dll", "CILADA.TestAssembly.Rock");
            WriteObjectInfo.WriteInfo(obj2);
            CreateAGiraffe();
        }

        public object CreateObject(string assemblyName, string typeName)
        {
            FileInfo fi = new FileInfo(assemblyName);
            Type type = Assembly.LoadFile(fi.FullName).GetType(typeName);
            object obj = System.Activator.CreateInstance(type);
            return obj;
        }

        public object CreateObject2(string assemblyName, string typeName)
        {
            object obj = System.Activator.CreateInstance(assemblyName, typeName);
            obj = ((ObjectHandle)obj).Unwrap();
            return obj;
        }

        public object CreateAGiraffe()
        {
            object obj = System.Activator.CreateInstance("CILADA.TestAssembly.dll", "CILADA.TestAssembly.Giraffe");
            obj = ((ObjectHandle)obj).Unwrap();
            return obj;
        }
    }

    class CreateObjectFromType
    {
        public T Create<T>()
        {
            return Activator.CreateInstance<T>();
        }
    }

    static class WriteObjectInfo
    {
        public static void WriteInfo(object obj)
        {
            Console.WriteLine("Created object from assembly {0}, of type {1}", obj.GetType().Assembly, obj.GetType().FullName);
        }
    }
}
